package org.zjt.config.properties;

import org.springframework.util.CollectionUtils;
import org.zjt.config.exception.RemoteConfigInitException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.zjt.config.register.ConfigNodeInfo;

import java.util.*;

/**
 * @author <a href="juntao.zhang@bkjk.com">juntao.zhang</a>
 * @Description:
 * @Package com.example.config
 * @date 2017/12/13 17:48
 * @see
 */
public class RemotePropertiesHolder<K,V> extends HashMap<K,V>{

    private static final Logger LOGGER = LoggerFactory.getLogger(RemotePropertiesHolder.class);

    private static final RestTemplate REST_TEMPLATE = new RestTemplate();


    private Integer retry;

    private HashMap properties;

    public static List<String> keys = new ArrayList<>();

    private RemotePropertiesHolder(int initialCapacity, float loadFactor,  Integer retry) {
        super(initialCapacity, loadFactor);
        this.retry = retry;
    }

    private RemotePropertiesHolder(int initialCapacity,  Integer retry) {
        super(initialCapacity);
        this.retry = retry;
    }

    private RemotePropertiesHolder( Integer retry) {
        this.retry = retry;
    }

    private RemotePropertiesHolder(Map<? extends K, ? extends V> m, String applicationName, Integer retry) {
        super(m);
        this.retry = retry;
    }

    public RemotePropertiesHolder() {
    }



    public Integer getRetry() {
        return retry;
    }

    public void setRetry(Integer retry) {
        this.retry = retry;
    }

    public boolean loadResource(ConfigNodeInfo configNodeInfo, ApplicationProperties applicationProperties) {
        ResponseEntity<HashMap> forEntity = null ;
        for (int i = 0; i < retry; i++) {
            forEntity = REST_TEMPLATE.getForEntity(configNodeInfo.getServerContext().toString()+"/{applicationName}/{dev}", HashMap.class,
                    applicationProperties.getName(),applicationProperties.getProfile());
            if (forEntity.getStatusCode().is2xxSuccessful())
                break;
        }
        if (Objects.isNull(forEntity) || !forEntity.getStatusCode().is2xxSuccessful())
            throw new RemoteConfigInitException("load remote properties fail");
        HashMap body = forEntity.getBody();
        body.forEach((k,v) -> LOGGER.debug("key:{}\tvalue:{}",k,v));
        properties = body;
        if (CollectionUtils.isEmpty(properties))
            return false;
        return true;
    }


    @Override
    public V get(Object key) {
        if (!keys.contains(String.valueOf(key)))
        keys.add(String.valueOf(key));
        return (V) properties.get(key);
    }

    @Override
    public V getOrDefault(Object key, V defaultValue) {
        if (Objects.isNull(properties.get(key)))
            return defaultValue;
        return (V) properties.get(key);
    }


    private static class LazyHolder {
        private static final RemotePropertiesHolder INSTANCE = new RemotePropertiesHolder();
    }

    public static final RemotePropertiesHolder getInstance() {
        return LazyHolder.INSTANCE;
    }

}
